package cn.tedu.justone.pack02;

/**
 * ZZ：JustOne
 * VX：Andylau2020smile
 * DY：JustOne2018
 * ZT：《》
 */
public class Demo12_深入思考wait_notify_notifyAll {

    //延伸思考一(不用讲)：
    //   Java官方为什么要设计成：wait、notify、notifyAll只能在synchronized中用锁对象调用？
    //景景理解：
    // 1,wait()的作用是让执行它的线程进入等待状态并交出锁对象，
    //   那么前提条件是该线程持有锁对象，
    //   也就意味着wait()只能在synchronized(lock)中使用。
    //   如果随时随地都执行wait()，它都没有持有锁对象，根本谈不上交出锁对象。
    // 2,lock.notify()和lock.notifyAll()的作用是唤醒锁对象lock上的等待线程，
    //   假如设计成随时随地都可以执行lock.notify()，那么会出现别人根本没有交出lock锁，
    //   但你唤醒了一大堆线程，这样唤醒就没有意义。
    //   唤醒的原因肯定是有人交出了lock锁，如何能知道有人交出了lock锁呢？
    //   最好的方式就是notify也呆在一个synchronized(lock)中，这样一来，
    //   只要notify能执行，说明肯定有人交出了lock锁。
    //   notify像是一个锁的旁观者，发现锁被交出来了就去呼叫该锁的等待队伍来竞争。

    //延伸思考二(不用讲)：
    //   Java官方为什么要设计成：
    //   主叫方lock.notify和被叫方lock.wait()各自的同步块必须持有同一个锁对象、且由同一个锁对象调用。
    //景景理解：
    // 1,为什么要锁对象调用而不用线程调用
    //   wait队伍也许不止一个，例如有一个manLock.wait()队伍，有一个womanLock.wait()队伍，
    //   如果wait()不由锁对象调用而由线程调用，就不能很明确的表现出该线程会进入哪个等待队伍，
    //   如果notify()不由锁对象调用而由线程调用，也不能很明确的表现出现在唤醒的是哪个队伍，
    //   而Java官方设计的是由锁对象来调用，例如manLock.wait()和manLock.notify()，
    //   这样能很明确的看出当前线程交出锁后是进入了哪个等待队伍，
    //   将来唤醒时也能很明确的看出唤醒的是那个队伍。
    // 2,为什么主叫方lock.notify()和被叫方lock.wait()各自的同步块必须持有同一个锁对象
    //   如果主叫方lock.notify()的同步块锁为synchronized(A)，
    //   而被叫方lock.wait()的同步块锁为synchronized(B)，
    //   就可能出现主叫方lock.notify()根本不知道B锁有没有被释放而对B锁的等待队伍进行盲目唤醒，
    //   而Java官方设计的要求双方必须使用同一个锁，例如：
    //   主叫方lock.notify()的同步块锁为synchronized(lock)，
    //   被叫方lock.wait()的同步块锁为synchronized(lock)，
    //   这样的好处在于只要lock.notify()能执行，说明肯定有人上交了锁对象lock，
    //   lock.notify()对lock等待队伍的唤醒才有意思。
    // 3,为什么主叫方lock.notify()和被叫方lock.wait()要由同一个锁对象来调用?
    //   一些程序执行manLock.wait()进入了manLock锁的等待队伍
    //   一些程序执行womanLock.wait()进入了womanLock锁的等待队伍
    //   如果manLock.notify()能唤醒womanLock锁的等待队伍，
    //   那样可能出现的情况是womanLock锁的等待队伍醒来后发现该队根本没有人上交锁对象，白醒一趟。
    //

}
